home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / utils / agrepsrc.zoo / mgrep.c < prev    next >
C/C++ Source or Header  |  1993-01-19  |  9KB  |  330 lines

  1. /* Copyright (c) 1991 Sun Wu and Udi Manber.  All Rights Reserved. */
  2. /* multipattern matcher */
  3. #include <stdio.h>
  4. #define MAXPAT  256
  5. #define MAXLINE 1024
  6. #define MAXSYM  256
  7. #define MAXMEMBER1 4096
  8. #define MAXPATFILE 260000
  9. #define BLOCKSIZE  8192
  10. #define MAXHASH    8192
  11. #define mm        8191
  12. #define max_num    30000  
  13. #define W_DELIM       252
  14. #define L_DELIM    10 
  15.  
  16. extern COUNT, FNAME, SILENT, FILENAMEONLY, num_of_matched;
  17. extern INVERSE;
  18. extern WORDBOUND, WHOLELINE, NOUPPER;
  19. extern unsigned char  CurrentFileName[], Progname[]; 
  20. extern total_line;
  21.  
  22. int LONG  = 0;
  23. int SHORT = 0;
  24. int p_size=0;
  25. unsigned char SHIFT1[MAXMEMBER1];
  26. unsigned char tr[MAXSYM];
  27. unsigned char tr1[MAXSYM];
  28. struct pat_list {
  29.     int  index;
  30.     struct pat_list *next;
  31. } *HASH[MAXHASH];
  32. struct pat_list  *pt, *qt;
  33. unsigned char buf[MAXPATFILE+BLOCKSIZE];
  34. unsigned char pat_spool[MAXPATFILE+2*max_num+MAXPAT];
  35. unsigned char *patt[max_num];
  36. unsigned char pat_len[max_num];
  37.  
  38.  
  39. prepf(fp)
  40. int fp;
  41. {
  42.     int length=0, i, p=1, pdx=0, num_pat;
  43.     unsigned char *pat_ptr=pat_spool, temp[10];
  44.     unsigned Mask = 15;
  45.     int num_read;
  46.  
  47.     while((num_read = read(fp, buf+length, BLOCKSIZE)) > 0) {
  48.     length = length + num_read;
  49.     if(length > MAXPATFILE) {
  50.         fprintf(stderr, "%s: maximum pattern file size is %d\n", Progname, MAXPATFILE);
  51.         exit(2);
  52.     }
  53.     }
  54.     buf[length] = '\n';
  55.     i = 0; p=1;
  56.     while(i<length) {
  57.     patt[p] = pat_ptr;
  58.     if(WORDBOUND) *pat_ptr++ = W_DELIM;
  59.     if(WHOLELINE) *pat_ptr++ = L_DELIM;
  60.     while((*pat_ptr = buf[i++]) != '\n') pat_ptr++;
  61.     if(WORDBOUND) *pat_ptr++ = W_DELIM;
  62.     if(WHOLELINE) *pat_ptr++ = L_DELIM;           /* Can't be both on */
  63.     *pat_ptr++ = 0;
  64.     p++;  
  65.     }
  66.     if(p>max_num) {
  67.     fprintf(stderr, "%s: maximum number of patterns is %d\n", Progname, max_num); 
  68.     exit(2);
  69.     }
  70.     for(i=1; i<20; i++) *pat_ptr = i;  /* boundary safety zone */
  71.     for(i=0; i< MAXSYM; i++) tr[i] = i;
  72.     if(NOUPPER) {
  73.     for(i='A'; i<= 'Z'; i++) tr[i] = i + 'a' - 'A';
  74.     }
  75.     if(WORDBOUND) {
  76.     tr['\n'] = tr['\t'] = tr[' '] = tr[','] = tr[';'] = tr[':'] = W_DELIM;
  77.         tr['!'] = tr['"'] = tr['?'] = tr['<'] = tr['>'] = W_DELIM;
  78.     tr['='] = tr['['] = tr[']'] = W_DELIM; 
  79.         tr['('] = tr[')'] = tr['$'] = tr['/'] = tr['\\'] = W_DELIM;
  80.     }
  81.     for(i=0; i< MAXSYM; i++) tr1[i] = tr[i]&Mask;
  82. #ifdef DEBUG
  83.   for(i=1; i<p; i++) printf("%s\n", patt[i]); fflush(stdout);
  84.   printf("\n\n");
  85. #endif
  86.     num_pat = p-1;
  87.     p_size = MAXPAT;
  88.     for(i=1 ; i <= num_pat; i++) {
  89.     p = strlen(patt[i]);
  90.     pat_len[i] = p;
  91.     if(p!=0 && p < p_size) p_size = p;
  92.     }
  93.     if(p_size == 0) {
  94.     fprintf(stderr, "%s: the pattern file is empty\n");
  95.     exit(2);
  96.     }
  97.     if(length > 400 && p_size > 2) LONG = 1;
  98.     if(p_size == 1) SHORT = 1;
  99.     for(i=0; i<MAXMEMBER1; i++) SHIFT1[i] = p_size - 2;
  100.     for(i=0; i<MAXHASH; i++) {
  101.     HASH[i] = 0;
  102.     }
  103.     for(i=1; i<= num_pat; i++) f_prep(i, patt[i]);
  104. }
  105.  
  106.  
  107. mgrep(fd)
  108. int fd;
  109.     register char r_newline = '\n';
  110.     unsigned char text[2*BLOCKSIZE+MAXLINE]; 
  111.     register int buf_end, num_read, i=0, j, start, end, residue = 0;
  112.  
  113.     text[MAXLINE-1] = '\n';  /* initial case */
  114.     start = MAXLINE-1;
  115.  
  116.     while( (num_read = read(fd, text+MAXLINE, BLOCKSIZE)) > 0) 
  117.     {
  118.        if(INVERSE && COUNT) countline(text+MAXLINE, num_read);
  119.        buf_end = end = MAXLINE + num_read -1 ;
  120.        while(text[end]  != r_newline && end > MAXLINE) end--;
  121.        residue = buf_end - end  + 1 ;
  122.        text[start-1] = r_newline;
  123.        if(SHORT) m_short(text, start, end);
  124.        else      monkey1(text, start, end);
  125.        if(FILENAMEONLY && num_of_matched) {
  126.         printf("%s\n", CurrentFileName);
  127.         return;
  128.        }
  129.        start = MAXLINE - residue;
  130.        if(start < 0) {
  131.             start = 1; 
  132.        }
  133.        strncpy(text+start, text+end, residue);
  134.     } /* end of while(num_read = ... */
  135.     text[MAXLINE] = '\n';
  136.     text[start-1] = '\n';
  137.     if(residue > 1) {
  138.         if(SHORT) m_short(text, start, end);
  139.         else      monkey1(text, start, end);
  140.     }
  141.     return;
  142. } /* end mgrep */
  143.  
  144. countline(text, len)
  145. unsigned char *text; int len;
  146. {
  147. int i;
  148.     for (i=0; i<len; i++) if(text[i] == '\n') total_line++;
  149. }
  150.  
  151.  
  152. monkey1( text, start, end  ) 
  153. int start, end; register unsigned char *text;
  154. {
  155. register unsigned char *textend;
  156. register unsigned hash, i;
  157. register unsigned char shift; 
  158. register int  m1, j, Long=LONG; 
  159. int pat_index, m=p_size; 
  160. int MATCHED=0;
  161. register unsigned char *qx;
  162. register struct pat_list *p;
  163. unsigned char *lastout;
  164. int OUT=0;
  165.  
  166. textend = text + end;
  167. m1 = m - 1;
  168. lastout = text+start+1;
  169. text = text + start + m1 ;
  170. while (text <= textend) {
  171.     hash=tr1[*text];
  172.     hash=(hash<<4)+(tr1[*(text-1)]);
  173.     if(Long) hash=(hash<<4)+(tr1[*(text-2)]);
  174.     shift = SHIFT1[hash];
  175.     if(shift == 0) {
  176.         hash=0;
  177.         for(i=0;i<=m1;i++)  {
  178.             hash=(hash<<4)+(tr1[*(text-i)]);
  179.         }
  180.         hash=hash&mm;
  181.         p = HASH[hash];
  182.         while(p != 0) {
  183.             pat_index = p->index;
  184.             p = p->next;
  185.             qx = text-m1;
  186.             j = 0;
  187.             while(tr[patt[pat_index][j]] == tr[*(qx++)]) j++;
  188.                 if (j > m1 ) { 
  189.                if(pat_len[pat_index] <= j) {
  190.                 if(text > textend) return;
  191.                         num_of_matched++;
  192.                         if(FILENAMEONLY || SILENT)  return;
  193.                 MATCHED=1;
  194.                     if(COUNT) {
  195.                       while (*text != '\n') text++;
  196.                 }
  197.                 else {
  198.                     if(!INVERSE) {
  199.                       if(FNAME) printf("%s: ",CurrentFileName);
  200.                                   while(*(--text) != '\n');
  201.                                   while(*(++text) != '\n') putchar(*text);
  202.                       printf("\n");
  203.                     }
  204.                     else {
  205.                       if(FNAME) printf("%s: ",CurrentFileName);
  206.                                   while(*(--text) != '\n');
  207.                     if(lastout < text) OUT=1;
  208.                     while(lastout < text) putchar(*lastout++);
  209.                     if(OUT) {
  210.                         putchar('\n');
  211.                         OUT=0;
  212.                     }
  213.                                   while(*(++text) != '\n');
  214.                     lastout=text+1;
  215.                     }
  216.                 }
  217. /*
  218.                 else {
  219.                       if(FNAME) printf("%s: ",CurrentFileName);
  220.                                   while(*(--text) != '\n');
  221.                                   while(*(++text) != '\n') putchar(*text);
  222.                       printf("\n");
  223.                 }
  224. */
  225.                }
  226.                     }
  227.             if(MATCHED) break;
  228.         }
  229.         if(!MATCHED) shift = 1;
  230.         else {
  231.             MATCHED = 0;
  232.             shift = m1;
  233.         }
  234.         }
  235.     text = text + shift;
  236.   }
  237.   if(INVERSE && !COUNT) while(lastout <= textend) putchar(*lastout++);
  238. }
  239.  
  240. m_short( text, start, end  ) 
  241. int start, end; register unsigned char *text;
  242. {
  243. register unsigned char *textend;
  244. register unsigned i; 
  245. register int  j; 
  246. register struct pat_list *p, *q;
  247. register int pat_index; 
  248. int MATCHED=0;
  249. int OUT=0;
  250. unsigned char *lastout;
  251. unsigned char *qx;
  252.  
  253. textend = text + end;
  254. lastout = text + start + 1;
  255. text = text + start - 1 ;
  256. while (++text <= textend) {
  257.         p = HASH[*text];
  258.         while(p != 0) {
  259.             pat_index = p->index;
  260.             p = p->next;
  261.             qx = text;
  262.             j = 0;
  263.             while(tr[patt[pat_index][j]] == tr[*(qx++)]) j++;
  264.             if(pat_len[pat_index] <= j) {
  265.                 if(text >= textend) return;
  266.                         num_of_matched++;
  267.                         if(FILENAMEONLY || SILENT)  return;
  268.                     if(COUNT) {
  269.                       while (*text != '\n') text++;
  270.                 }
  271.                 else {
  272.                       if(FNAME) printf("%s: ",CurrentFileName);
  273.                     if(!INVERSE) {
  274.                                   while(*(--text) != '\n');
  275.                                   while(*(++text) != '\n') putchar(*text);
  276.                       printf("\n");
  277.                     MATCHED = 1;
  278.                     }
  279.                     else {
  280.                                   while(*(--text) != '\n');
  281.                     if(lastout < text) OUT=1;
  282.                     while(lastout < text) putchar(*lastout++);
  283.                     if(OUT) {
  284.                         putchar('\n');
  285.                         OUT=0;
  286.                     }
  287.                                   while(*(++text) != '\n');
  288.                     lastout=text+1;
  289.                     MATCHED = 1;
  290.                     }
  291.                 }
  292.                     }
  293.             if(MATCHED) break;
  294.         }
  295.         MATCHED = 0;
  296.   } /* while */
  297.   if(INVERSE && !COUNT) while(lastout <= textend) putchar(*lastout++);
  298. }
  299.  
  300. f_prep(pat_index, Pattern)
  301. unsigned char *Pattern ; int pat_index;
  302. {
  303. int i, j, m;
  304. register unsigned hash, Mask=15;
  305.     m = p_size;
  306.     for (i = m-1; i>=(1+LONG); i--) {
  307.         has